package deviceKey

/*
    #cgo CFLAGS: -I../
    #cgo LDFLAGS: -L../ -ldecd -lm
	#include "compute.h"
	#include "device.h"
	#include "key.h"
	#include "manager.h"
	#include "xdma.h"
    #include <stdlib.h>
*/
import "C"
import (
	"encoding/hex"
	"errors"
	"fmt"
	"strings"
	"unsafe"
)

//// 备份设备密钥
//func NFHE_DECD_Device_Backup(ls_password string, ls_password_len int) (string, error) {
//	var err error                  // 出错返回值
//	var ret string                 // 功能返回密钥值
//	var ll_len int                 //口令长度变量
//	ll_len = int(len(ls_password)) // 强制类型转换
//	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
//		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
//		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
//		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
//		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
//		bt := make([]byte, 512)                                        // 给bt变量复制512个字节
//		ls_device_key := GetCharPointer(bt)                            //用CGO语言进行强制类型转换字符
//		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
//		if rv != 0 {
//			cw := fmt.Sprintf("%x", rv)
//			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
//			return "", err
//		}
//		rv = C.FHEKmg_Backup_DeviceKeyPair(ls_password_C1, Password_Len, ls_device_key) // 备份加密卡的设备主密钥
//		if rv != 0 {
//			cw := fmt.Sprintf("%x", rv)
//			err = errors.New("出错信息:备份设备密钥时出错！错误号：" + cw)
//		} else {
//			ret = C.GoStringN(ls_device_key, 512) // 取出设备主密钥值
//			return ret, nil
//		}
//	} else {
//		err = errors.New("出错信息:口令长度必须大于等于8。")
//	}
//	return ret, err
//}

//// 恢复设备密钥
//func NFHE_DECD_Device_Restore(ls_password string, ls_password_len int, deviceKey []byte) error {
//	var err error                  // 出错返回值
//	var ll_len int                 //口令长度变量
//	ll_len = int(len(ls_password)) // 强制类型转换
//	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
//		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
//		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
//		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
//		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
//		deviceKeyTmpStr := hex.EncodeToString(deviceKey)[0:512]        // 将byte转换字符串
//		deviceKeyTmpStr1 := C.CString(deviceKeyTmpStr)                 // 将go字符串转换C字符串
//		var deviceKeyTmp = (*C.char)(unsafe.Pointer(deviceKeyTmpStr1)) // 将C字符串转换C.char指针
//		defer C.free(unsafe.Pointer(deviceKeyTmpStr1))                 // 动态回收内存空间
//		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
//		if rv != 0 {
//			cw := fmt.Sprintf("%x", rv)
//			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
//			return err
//		}
//		rv = C.FHEKmg_Restore_DeviceKeyPair(ls_password_C1, Password_Len, deviceKeyTmp) // 恢复加密卡的设备主密钥
//		if rv != 0 {
//			cw := fmt.Sprintf("%x", rv)
//			err = errors.New("出错信息:恢复设备密钥时出错！错误号：" + cw)
//		} else {
//			return nil
//		}
//	} else {
//		err = errors.New("出错信息:口令长度必须大于等于8。")
//	}
//	return err
//}

// 备份保护密钥
func NFHE_DECD_ProKey_Backup(ls_password string, ls_password_len int) (string, error) {
	var err error                  // 出错返回值
	var ret string                 // 功能返回密钥值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否大于等于16
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
		bt := make([]byte, 233)                                        // 给bt变量复制232个字节
		ls_ProKey := GetCharPointer(bt)                                //用CGO语言进行强制类型转换字符
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return "", err
		}
		rv = C.FHEKmg_Backup_ProKey(ls_password_C1, Password_Len, ls_ProKey) // 备份加密卡的设备主密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:备份保护密钥时出错！错误号：" + cw)
		} else {
			ret = C.GoStringN(ls_ProKey, 232) // 取出设备主密钥值
			rv = C.FHEKmg_UnVerification()    //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return ret, nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于16。")
	}
	return ret, err
}

// 恢复保护密钥
func NFHE_DECD_Prokey_Restore(ls_password string, ls_password_len int, ProKey []byte) error {
	var err error                  // 出错返回值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换

		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len) //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return err
		}

		ProKeyTmpStr := strings.ToUpper(hex.EncodeToString(ProKey))
		//fmt.Println(ProKeyTmpStr)
		ProKeyTmpStr1 := C.CString(ProKeyTmpStr)
		var ProKeyTmp = (*C.char)(unsafe.Pointer(ProKeyTmpStr1))
		defer C.free(unsafe.Pointer(ProKeyTmpStr1))                           // 动态回收内存空间
		rv = C.FHEKmg_Restore_ProKey(ls_password_C1, Password_Len, ProKeyTmp) // 备份加密卡的设备主密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:恢复保护密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于16。")
	}
	return err
}

// 生成用户密钥
func NFHE_DECD_Create_UserKey(ls_password string, ls_password_len int, UserIndex uint, UserCode string, UserLen uint) error {
	var err error                  // 出错返回值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:生成用户密钥管理员身份认证时出错！错误号：" + cw)
			return err
		}
		UserIndex1 := C.uint(UserIndex)                                    // 用CGO语言的强制类型转换
		UserLen1 := C.uint(UserLen)                                        // 用CGO语言的强制类型转换
		UserCode_C := C.CString(UserCode)                                  // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(UserCode_C))                           // 动态回收内存空间
		var UserCode_C1 = (*C.uchar)(unsafe.Pointer(UserCode_C))           // 将C字符串转换C.uchar指针
		rv = C.FHEKmg_Create_UsrKeyPair(UserIndex1, UserCode_C1, UserLen1) // 生成用户密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:生成用户密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return err
}

// 备份用户密钥
func NFHE_DECD_UserKey_Backup(ls_password string, ls_password_len int) (string, error) {
	var err error                  // 出错返回值
	var ret string                 // 功能返回密钥值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
		bt := make([]byte, 384)                                        // 给bt变量复制384个字节
		ls_user_key := GetCharPointer(bt)                              //用CGO语言进行强制类型转换字符
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return "", err
		}
		UserIndex1 := C.uint(1)                                  // 用CGO语言的强制类型转换
		rv = C.FHEKmg_Backup_UsrKeyPair(UserIndex1, ls_user_key) // 备份用户密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:备份用户密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			ret = C.GoStringN(ls_user_key, 384) // 取出用户密钥值
			return ret, nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return ret, err
}

// 恢复用户密钥
func NFHE_DECD_UserKey_Restore(ls_password string, ls_password_len int, UserKey []byte) error {
	var err error                  // 出错返回值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换

		UserKeyTmpStr := hex.EncodeToString(UserKey)[0:384]        // 将byte转换字符串
		UserKeyTmpStr1 := C.CString(UserKeyTmpStr)                 // 将go字符串转换C字符串
		var UserKeyTmp = (*C.char)(unsafe.Pointer(UserKeyTmpStr1)) // 将C字符串转换C.char指针
		defer C.free(unsafe.Pointer(UserKeyTmpStr1))               // 动态回收内存空间
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)  //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return err
		}
		rv = C.FHEKmg_Restore_UsrKeyPair(1, UserKeyTmp) // 恢复用户密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:恢复用户密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return err
}

// 生成密钥加密密钥
func NFHE_DECD_Create_KEK(ls_password string, ls_password_len int, KEKIndex uint) error {
	var err error                  // 出错返回值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:生成用户密钥管理员身份认证时出错！错误号：" + cw)
			return err
		}
		KEKIndex1 := C.uint(KEKIndex)         // 用CGO语言的强制类型转换
		rv = C.FHEKmg_Create_Kekey(KEKIndex1) // 生成密钥加密密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:生成密钥加密密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return err
}

// 备份密钥加密密钥
func NFHE_DECD_KEK_Backup(ls_password string, ls_password_len int) (string, error) {
	var err error                  // 出错返回值
	var ret string                 // 功能返回密钥值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换
		bt := make([]byte, 32)                                         // 给bt变量复制384个字节
		ls_KEK := GetCharPointer(bt)                                   //用CGO语言进行强制类型转换字符
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len)      //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return "", err
		}
		KEKIndex1 := C.uint(0)                        // 用CGO语言的强制类型转换
		rv = C.FHEKmg_Backup_KeKey(KEKIndex1, ls_KEK) // 备份密钥加密密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:备份密钥加密密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			ret = C.GoStringN(ls_KEK, 32) // 取出密钥加密密钥值
			return ret, nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return ret, err
}

// 恢复密钥加密密钥
func NFHE_DECD_KEK_Restore(ls_password string, ls_password_len int, KEK []byte) error {
	var err error                  // 出错返回值
	var ll_len int                 //口令长度变量
	ll_len = int(len(ls_password)) // 强制类型转换
	if ll_len >= ls_password_len { // 判断口令长度是否大于等于8
		ls_password_C := C.CString(ls_password)                        // 将go字符串转换C字符串
		defer C.free(unsafe.Pointer(ls_password_C))                    // 动态回收内存空间
		var ls_password_C1 = (*C.uchar)(unsafe.Pointer(ls_password_C)) // 将C字符串转换C.uchar指针
		Password_Len := C.uint(ls_password_len)                        // 用CGO语言的强制类型转换

		KEYTmpStr := hex.EncodeToString(KEK)[0:32]                // 将byte转换字符串
		KEKTmpStr1 := C.CString(KEYTmpStr)                        // 将go字符串转换C字符串
		var KEKTmp = (*C.char)(unsafe.Pointer(KEKTmpStr1))        // 将C字符串转换C.char指针
		defer C.free(unsafe.Pointer(KEKTmpStr1))                  // 动态回收内存空间
		rv := C.FHEKmg_Verification(ls_password_C1, Password_Len) //管理员身份认证
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err := errors.New("出错信息:管理员身份认证时出错！错误号：" + cw)
			return err
		}
		KEKIndex1 := C.uint(0)
		rv = C.FHEKmg_Restore_KeKey(KEKIndex1, KEKTmp) // 恢复密钥加密密钥
		if rv != 0 {
			cw := fmt.Sprintf("%x", rv)
			err = errors.New("出错信息:恢复密钥加密密钥时出错！错误号：" + cw)
		} else {
			rv = C.FHEKmg_UnVerification() //撤销管理员身份
			if rv != 0 {
				cw := fmt.Sprintf("%x", rv)
				err = errors.New("出错信息:撤销管理员身份时出错！错误号：" + cw)
			}
			return nil
		}
	} else {
		err = errors.New("出错信息:口令长度必须大于等于8。")
	}
	return err
}

// 转换字节为字符指针
func GetCharPointer(val []byte) *C.char {
	return (*C.char)(unsafe.Pointer(&val[0]))
}

func GetBytePointer(val []uint8) *C.char {
	return (*C.char)(unsafe.Pointer(&val[0]))
}
